using System.Threading;

namespace muduoDotNet
{
    /// <summary>
    /// EventLoopThread类，用于创建一个线程并在该线程中运行EventLoop
    /// </summary>
    public class EventLoopThread : IDisposable
    {
        private readonly Thread _thread;
        private EventLoop _loop;
        private readonly ManualResetEventSlim _startedEvent;
        private bool _disposed;
        private readonly Action _threadInitCallback;

        public EventLoopThread(Action threadInitCallback = null)
        {
            _threadInitCallback = threadInitCallback;
            _thread = new Thread(ThreadFunc);
            _loop = null;
            _startedEvent = new ManualResetEventSlim(false);
            _disposed = false;
        }

        public EventLoop Loop => _loop;

        /// <summary>
        /// 启动线程
        /// </summary>
        /// <returns>EventLoop对象</returns>
        public EventLoop StartLoop()
        {
            if (!_thread.IsAlive)
            {
                _thread.Start();
                
                // 等待线程初始化完成
                _startedEvent.Wait();
            }
            
            return _loop;
        }

        /// <summary>
        /// 线程函数
        /// </summary>
        private void ThreadFunc()
        {
            // 初始化EventLoop
            _loop = new EventLoop();
            
            // 设置线程本地存储
            ThreadLocalEventLoop.SetEventLoop(_loop);
            
            // 调用初始化回调
            _threadInitCallback?.Invoke();
            
            // 通知启动完成
            _startedEvent.Set();
            
            // 运行事件循环
            _loop.Start();
            
            // 清除线程本地存储
            ThreadLocalEventLoop.ClearEventLoop();
            _loop = null;
        }

        public void Dispose()
        {
            if (!_disposed)
            {
                _disposed = true;
                
                if (_loop != null)
                {
                    // 停止事件循环
                    _loop.Stop();
                }
                
                // 等待线程结束
                if (_thread.IsAlive)
                {
                    _thread.Join();
                }
                
                _startedEvent.Dispose();
            }
        }
    }
}